﻿using AutoMapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using RuYiAdmin.Net.Common.Global;
using RuYiAdmin.Net.Common.Utility;
using RuYiAdmin.Net.Entity.BusinessDTO.SystemManagement;
using RuYiAdmin.Net.Entity.BusinessEntity.System;
using RuYiAdmin.Net.Entity.BusinessEntity.SystemManagement;
using RuYiAdmin.Net.Entity.BusinessEnum;
using RuYiAdmin.Net.Entity.CoreEntity;
using RuYiAdmin.Net.Entity.CoreEnum;
using RuYiAdmin.Net.Service.BusinessService.ActiveMQ;
using RuYiAdmin.Net.Service.BusinessService.Redis;
using RuYiAdmin.Net.Service.BusinessService.SystemManagement.OrgUser;
using RuYiAdmin.Net.Service.BusinessService.SystemManagement.User;
using RuYiAdmin.Net.WebApi.AppCode.Base;
using RuYiAdmin.Net.WebApi.AppCode.Filter;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using ActionResult = RuYiAdmin.Net.Entity.CoreEntity.ActionResult;

// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860

namespace RuYiAdmin.Net.WebApi.Controllers.SystemManagement
{
    /// <summary>
    /// 用户管理接口
    /// </summary>
    public class UserManagementController : BaseController<SysUser>
    {
        /// <summary>
        /// 用户接口实例
        /// </summary>
        private readonly IUserService userService;

        /// <summary>
        /// 机构与用户接口实例
        /// </summary>
        private readonly IOrgUserService orgUserService;

        /// <summary>
        /// AutoMapper实例
        /// </summary>
        private readonly IMapper mapper;

        /// <summary>
        /// Redis接口实例
        /// </summary>
        private readonly IRedisService redisService;

        /// <summary>
        /// ActiveMQ接口实例
        /// </summary>
        private readonly IActiveMQService activeMQService;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="userService"></param>
        /// <param name="orgUserService"></param>
        /// <param name="mapper"></param>
        /// <param name="redisService"></param>
        /// <param name="activeMQService"></param>
        public UserManagementController(IUserService userService, IOrgUserService orgUserService, IMapper mapper,
            IRedisService redisService, IActiveMQService activeMQService) : base(userService)
        {
            this.userService = userService;
            this.orgUserService = orgUserService;
            this.mapper = mapper;
            this.redisService = redisService;
            this.activeMQService = activeMQService;
        }

        /// <summary>
        /// 查询用户列表
        /// </summary>
        /// <param name="queryCondition">查询条件</param>
        /// <returns>ActionResult</returns>
        [HttpPost]
        [Log(OperationType.QueryList)]
        [Permission("user:query:list")]
        public IActionResult Post(QueryCondition queryCondition)
        {
            var actionResult = this.userService.SqlQuery<SysUserDTO>(queryCondition, "sqls:sql:query_sysuser");

            //调用日志
            Logger.Info(JsonConvert.SerializeObject(actionResult));

            return Ok(actionResult);
        }

        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <param name="userId">用户编号</param>
        /// <returns>ActionResult</returns>
        [HttpGet("{userId}")]
        [Log(OperationType.QueryEntity)]
        [Permission("user:query:list")]
        public IActionResult GetById(Guid userId)
        {
            var actionResult = this.userService.GetById(userId);
            return Ok(actionResult);
        }

        /// <summary>
        /// 新增用户
        /// </summary>
        /// <param name="userDTO">用户对象</param>
        /// <returns>ActionResult</returns>
        [HttpPost]
        [Log(OperationType.AddEntity)]
        [Permission("user:add:entity")]
        public IActionResult Add([FromBody] SysUserDTO userDTO)
        {
            var defaultPassword = GlobalContext.SystemConfig.DefaultPassword;
            var aesKey = GlobalContext.SystemConfig.AesKey;
            userDTO.Password = AesUtil.AesEncrypt(defaultPassword, aesKey);

            //DTO TO POCO
            var user = mapper.Map<SysUser>(userDTO);

            //新增用户
            this.userService.Add(user);

            //用户与机构关联
            var orgUser = new SysOrgUser();
            orgUser.OrgId = userDTO.OrgId;
            orgUser.UserId = user.Id;

            //新增机构与用户关系
            this.orgUserService.Add(orgUser);

            userDTO = mapper.Map<SysUserDTO>(user);

            var actionResult = new ActionResult();

            actionResult.HttpStatusCode = HttpStatusCode.OK;
            actionResult.Message = new String("OK");
            actionResult.Object = userDTO;

            return Ok(actionResult);
        }

        /// <summary>
        /// 编辑用户
        /// </summary>
        /// <param name="userDTO">用户对象</param>
        /// <returns>ActionResult</returns>
        [HttpPut]
        [Log(OperationType.EditEntity)]
        [Permission("user:edit:entity")]
        public IActionResult Put([FromBody] SysUserDTO userDTO)
        {
            //DTO TO POCO
            var user = mapper.Map<SysUser>(userDTO);
            var actionResult = this.userService.Update(user);

            if (user.IsEnabled.Equals(0))
            {
                var tokenKey = GlobalContext.SystemConfig.TokenKey;
                var limitCount = GlobalContext.SystemConfig.LogonCountLimit;

                if (limitCount > 0 && limitCount.Equals(1))
                {
                    this.redisService.Delete(new String[] { "user_" + user.Id, String.Format(tokenKey, user.Id, 1) });
                }
                else if (limitCount > 1)
                {
                    var array = new String[limitCount];

                    for (var i = 1; i <= limitCount; i++)
                    {
                        array[i - 1] = String.Format(tokenKey, user.Id, i);
                    }

                    this.redisService.Delete(array);
                }

                var msg = new SystemMessage();

                msg.Message = "ForceLogout";
                msg.MessageType = MessageType.ForceLogout;
                msg.Object = user;

                var topic = "_Message";

                this.activeMQService.SendTopic(JsonConvert.SerializeObject(msg), topic);
            }

            return Ok(actionResult);
        }

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="userId">用户编号</param>
        /// <returns>ActionResult</returns>
        [HttpDelete("{userId}")]
        [Permission("user:del:entities")]
        [Log(OperationType.DeleteEntity)]
        public IActionResult Delete(Guid userId)
        {
            var actionResult = this.userService.DeleteEntity(userId);
            return Ok(actionResult);
        }

        /// <summary>
        /// 批量删除用户
        /// </summary>
        /// <param name="ids">编号数组</param>
        /// <returns>ActionResult</returns>
        [HttpDelete("{ids}")]
        [Log(OperationType.DeleteEntity)]
        [Permission("user:del:entities")]
        public IActionResult DeleteRange(String ids)
        {
            var actionResult = this.userService.DeleteEntities(ids);
            return Ok(actionResult);
        }

        /// <summary>
        /// 获取验证码
        /// </summary>
        /// <returns>ActionResult</returns>
        [HttpGet]
        [AllowAnonymous]
        [Log(OperationType.Logon)]
        public IActionResult GetCaptcha()
        {
            var actionResult = this.userService.GetCaptcha();
            return Ok(actionResult);
        }

        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="loginDTO">登录信息</param>
        /// <returns>ActionResult</returns>
        [HttpPost]
        [AllowAnonymous]
        [Log(OperationType.Logon)]
        public IActionResult Logon([FromBody] LoginDTO loginDTO)
        {
            var actionResult = this.userService.Logon(loginDTO);
            return Ok(actionResult);
        }

        /// <summary>
        /// 退出登录
        /// </summary>
        /// <param name="token">token</param>
        /// <returns>ActionResult</returns>
        [HttpGet("{token}")]
        [Log(OperationType.Logout)]
        public IActionResult Logout(String token)
        {
            var actionResult = this.userService.Logout(token);
            return Ok(actionResult);
        }

        /// <summary>
        /// 强制退出
        /// </summary>
        /// <param name="token">token</param>
        /// <returns>ActionResult</returns>
        [HttpGet("{token}")]
        [Log(OperationType.ForceLogout)]
        public IActionResult ForceLogout(String token)
        {
            var actionResult = this.userService.Logout(token);

            var msg = new SystemMessage();

            msg.Message = "ForceLogout";
            msg.MessageType = MessageType.ForceLogout;

            var topic = "_Message";

            this.activeMQService.SendTopic(JsonConvert.SerializeObject(msg), topic);

            return Ok(actionResult);
        }

        /// <summary>
        /// 按机构编号获取用户信息
        /// </summary>
        /// <param name="orgId">机构编号</param>
        /// <returns>ActionResult</returns>
        [HttpGet("{orgId}")]
        [Log(OperationType.QueryList)]
        public IActionResult GetUserByOrgId(Guid orgId)
        {
            var queryCondition = new QueryCondition();

            queryCondition.QueryItems = new List<QueryItem>();

            queryCondition.QueryItems.Add(new QueryItem()
            {
                Field = "OrgId",
                DataType = DataType.Guid,
                QueryMethod = QueryMethod.Equal,
                Value = orgId
            });

            var actionResult = this.userService.SqlQuery<SysUserDTO>(queryCondition, "sqls:sql:query_sysuser");

            return Ok(actionResult);
        }

        /// <summary>
        /// 更新密码
        /// </summary>
        /// <param name="data">参数</param>
        /// <returns>ActionResult</returns>
        [HttpPost]
        [Log(OperationType.UpdatePassword)]
        public IActionResult UpdatePassword([FromBody] PasswordDTO data)
        {
            var actionResult = this.userService.UpdatePassword(data);

            return Ok(actionResult);
        }
    }
}
